package at.gv.bmwf.fons.model.ontology;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;

import javax.naming.NameNotFoundException;

import at.gv.bmwf.fons.model.ontology.static_impl.StaticSelection;
import at.gv.bmwf.fons.model.ontology.uris.VONT;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.RDFS;

public class SelectionFactory {
	private final Set<Selection> selections = Sets.newTreeSet();
	private final OntModel viewModel;
	
	private final AtomFactory atomFactory;
		
	public SelectionFactory (OntModel viewModel, AtomFactory atomFactory) {
		this.viewModel = viewModel;		
		this.atomFactory = atomFactory;
	}
	
	public List<Selection> getSelections() {
		final String queryString = String.format("SELECT ?selection WHERE { " +
				"?selection a <%s> } ", VONT.Selection);
		
		ResultSet result = QueryExecutionFactory.create(QueryFactory.create(queryString), viewModel).execSelect();
		while (result.hasNext()) {
			QuerySolution solution = result.next();
			selections.add(new StaticSelection(solution.getResource("?selection"), atomFactory));
		}
		return Lists.newArrayList(selections);
	}
	
	public Selection getSelectionByName (String byName) throws NameNotFoundException {
		final String query = String.format(
				"SELECT ?selection WHERE { ?selection a <%s>. ?selection <%s> ?label. " +
				"FILTER regex(?label, \"^%s\") } LIMIT 1",
				VONT.Selection, RDFS.label, byName);
						
		ResultSet result = QueryExecutionFactory.create(QueryFactory.create(query), viewModel).execSelect();
		Resource resource = null; 
				
		while (result.hasNext()) {
			QuerySolution solution = result.next();
			resource = solution.getResource("?selection");
			for (Selection selection: selections) {
				if (selection.getResource().equals(resource)) return selection;
			}
		}
		
		if (resource == null) throw new NameNotFoundException(byName);
				
		Selection selection = new StaticSelection(resource, atomFactory);
		selections.add(selection);
		return selection;
	}
	
	public Selection getSelectionByUri (String uri) {
		Individual selection = viewModel.getIndividual(uri);
		if (selection == null) throw new NoSuchElementException(uri);
		
		for (Selection sel: selections) {
			if (selection.equals(sel.getResource())) return sel;
		}
		
		Selection sel = new StaticSelection(selection, atomFactory);
		selections.add(sel);
		return sel;
	}
}

